package com.kelaite.procurement.service.impl;

import java.util.Date;
import java.util.List;

import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
import javax.transaction.Transactional;

import org.apache.commons.lang3.StringUtils;
import org.hibernate.Criteria;
import org.hibernate.Session;
import org.hibernate.criterion.Restrictions;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import com.kelaite.procurement.constants.BizType;
import com.kelaite.procurement.constants.CurrencyTypeEnum;
import com.kelaite.procurement.constants.OrderStatusEnum;
import com.kelaite.procurement.dto.PurchaseOrderDTO;
import com.kelaite.procurement.dto.UserDTO;
import com.kelaite.procurement.entity.TCity;
import com.kelaite.procurement.entity.TCompany;
import com.kelaite.procurement.entity.TProvince;
import com.kelaite.procurement.entity.TPurchaseOrder;
import com.kelaite.procurement.entity.TSalesOrder;
import com.kelaite.procurement.entity.TUser;
import com.kelaite.procurement.entity.TVendor;
import com.kelaite.procurement.exception.BusinessException;
import com.kelaite.procurement.repository.CityRepository;
import com.kelaite.procurement.repository.CompanyRepository;
import com.kelaite.procurement.repository.PipelinePublicRepository;
import com.kelaite.procurement.repository.PurchaseOrderRepository;
import com.kelaite.procurement.repository.SalesOrderRepository;
import com.kelaite.procurement.repository.UserRepository;
import com.kelaite.procurement.repository.VendorRepository;
import com.kelaite.procurement.service.PurchaseOrderService;
import com.kelaite.procurement.utils.CommonUtils;
import com.kelaite.procurement.utils.ConvertUtil;
import com.kelaite.procurement.utils.CurrentUserUtils;

@Service
@Transactional
public class PurchaseOrderServiceImpl implements PurchaseOrderService {

	@Autowired
	private PurchaseOrderRepository purchaseOrderRepository;

	@Autowired
	private VendorRepository vendorRepository;

	@Autowired
	private UserRepository userRepository;

	@Autowired
	private CityRepository cityRepository;

	@Autowired
	private SalesOrderRepository salesOrderRepository;

	@Autowired
	private CompanyRepository companyRepository;

	@Autowired
	private PipelinePublicRepository pipelinePublicRepository;

	@PersistenceContext
	private EntityManager em;

	@Override
	public TPurchaseOrder getObject(Long id) {

		return this.purchaseOrderRepository.findOne(id);
	}

	@Override
	public List<TPurchaseOrder> getAll() {

		return this.purchaseOrderRepository.findAll();
	}

	@Override
	public void deleteByObject(TPurchaseOrder persistence) {

		this.purchaseOrderRepository.delete(persistence);
	}

	@Override
	public void deleteByPrimaryKey(Long id) {

		this.purchaseOrderRepository.delete(id);
	}

	@SuppressWarnings("unchecked")
	@Override
	public List<TPurchaseOrder> getByProperty(String property, Object value) {

		Session session = (org.hibernate.Session) em.getDelegate();
		Criteria criteria = session.createCriteria(TPurchaseOrder.class).add(
				Restrictions.eq(property, value));
		return criteria.list();
	}

	@Override
	public PurchaseOrderDTO save(PurchaseOrderDTO purchaseOrderDTO) {

		//
		if (null == purchaseOrderDTO) {
			throw new BusinessException("purchaseOrder is null. ");
		}
		Long pipelinePublicId = purchaseOrderDTO.getPipelinePublicId();
		if (pipelinePublicId == null || pipelinePublicId <= 0) {
			throw new BusinessException("pipelinePublicId is illegal. "
					+ purchaseOrderDTO.toString());
		}
		if (null == purchaseOrderDTO.getStartTime()
				|| null == purchaseOrderDTO.getExpiredTime()) {
			throw new BusinessException("StartTime or  ExpiredTime is null. "
					+ purchaseOrderDTO.toString());
		}
		if (purchaseOrderDTO.getStartTime().after(
				purchaseOrderDTO.getExpiredTime())) {
			throw new BusinessException(
					"StartTime must less than  ExpiredTime. "
							+ purchaseOrderDTO.toString());
		}
		if (null == purchaseOrderDTO.getPrice()
				|| 0 >= purchaseOrderDTO.getPrice()) {
			throw new BusinessException("order price must greater than zero. "
					+ purchaseOrderDTO.toString());
		}
		if (StringUtils.isBlank(purchaseOrderDTO.getPurchaseOrderNo())) {
			throw new BusinessException("purchaseOrderNo is null. "
					+ purchaseOrderDTO.toString());
		}
		// CurrentUser
		UserDTO cUser = CurrentUserUtils.getInstance().getUser();
		if (null == cUser) {
			throw new BusinessException("Current User is null. ");
		}
		// Date
		Date now = new Date();
		// TCity
		if (null == purchaseOrderDTO.getCityId()
				|| purchaseOrderDTO.getCityId() <= 0) {
			throw new BusinessException("cityId invalid. "
					+ purchaseOrderDTO.toString());
		}
		TCity city = cityRepository.getOne(purchaseOrderDTO.getCityId());
		if (null == city) {
			throw new BusinessException("no city exsist. "
					+ purchaseOrderDTO.toString());
		}
		// TProvince
		TProvince province = city.gettProvince();
		if (null == province) {
			throw new BusinessException("provinceId is invalid. "
					+ purchaseOrderDTO.toString());
		}
		if (!province.getId().equals(purchaseOrderDTO.getProvinceId())) {
			throw new BusinessException("provinceId is invalid. "
					+ purchaseOrderDTO.toString());
		}
		// Address
		String address = purchaseOrderDTO.getAddress();
		if (StringUtils.isBlank(address)) {
			throw new BusinessException("address is null. "
					+ purchaseOrderDTO.toString());
		}
		// 签约公司验证
		if (purchaseOrderDTO.getCompanyId() == null
				|| purchaseOrderDTO.getCompanyId() <= 0) {
			throw new BusinessException("companyId is invalid. "
					+ purchaseOrderDTO.toString());
		}
		TCompany company = companyRepository.findOne(purchaseOrderDTO
				.getCompanyId());
		if (null == company) {
			throw new BusinessException("no sign company exsist. "
					+ purchaseOrderDTO.toString());
		}
		// vendor有效性验证
		TVendor dbVendor = vendorRepository.findOne(purchaseOrderDTO
				.getVendorId());
		if (null == dbVendor
				|| dbVendor.gettClient().getId() != cUser.gettCompany().getId()
				|| dbVendor.gettSupplier().getId() != purchaseOrderDTO
						.getSupplierId()
				|| now.after(dbVendor.getStatusToDate())) {
			throw new BusinessException("vendor is invalid. "
					+ purchaseOrderDTO.toString());
		}
		// 合同负责人
		if (purchaseOrderDTO.getUserId() == null
				|| purchaseOrderDTO.getUserId() <= 0) {
			throw new BusinessException("userId is invalid. "
					+ purchaseOrderDTO.toString());
		}
		TUser dbUser = userRepository.findOne(purchaseOrderDTO.getUserId());
		if (null == dbUser) {
			throw new BusinessException("userId is invalid. "
					+ purchaseOrderDTO.toString());
		}
		// 保存数据到t_purchase_order表
		TPurchaseOrder dbPurchaseOrder = ConvertUtil.convertObj(
				purchaseOrderDTO, TPurchaseOrder.class);
		dbPurchaseOrder.setCreatedBy(CurrentUserUtils.getInstance()
				.getUsername());
		dbPurchaseOrder.setDeliverAddress(province.getProvinceName()
				+ city.getCityName() + address);
		dbPurchaseOrder.setGmtCreateTime(now);
		dbPurchaseOrder.setGmtUpdateTime(now);
		dbPurchaseOrder
				.setOrderStatus((short) OrderStatusEnum.CREATED.getVal());
		dbPurchaseOrder.setSalesOrderNo(CommonUtils
				.generateBizNo(BizType.SELL_ORDER));
		dbPurchaseOrder.settCompany(company);
		dbPurchaseOrder.settUser(dbUser);
		dbPurchaseOrder.settVendor(dbVendor);
		dbPurchaseOrder.setUpdatedBy(dbPurchaseOrder.getCreatedBy());
		dbPurchaseOrder = purchaseOrderRepository.save(dbPurchaseOrder);
		// 保存相应的记录到t_sales_order表
		TSalesOrder dbSalesOrder = ConvertUtil.convertObj(dbPurchaseOrder,
				TSalesOrder.class);
		dbSalesOrder.setId(null);
		dbSalesOrder.setPurchaseOrderNo(dbPurchaseOrder.getPurchaseOrderNo());
		dbSalesOrder.setSalesOrderNo(dbPurchaseOrder.getSalesOrderNo());
		dbSalesOrder.setSalesOrderDesc(null);
		dbSalesOrder.settCompany(dbVendor.gettSupplier());
		dbSalesOrder.settUser(null);
		dbSalesOrder.settVendor(dbVendor);
		salesOrderRepository.save(dbSalesOrder);
		// 修改pipelinePublic记录状态为已创建合同
		pipelinePublicRepository.updatePipelinePublicContractCreated(
				pipelinePublicId, true, now, dbPurchaseOrder.getCreatedBy());
		return ConvertUtil.convertObj(dbPurchaseOrder, PurchaseOrderDTO.class);
	}

	@Override
	public String getCurrencyByOrderId(Long purchaseOrderId) {

		if (null == purchaseOrderId || purchaseOrderId <= 0) {
			throw new BusinessException(String.format(
					"purchaseOrderId[%s] is illegal", purchaseOrderId));
		}
		short currency = purchaseOrderRepository
				.findCurrencyByOrderId(purchaseOrderId);
		return CurrencyTypeEnum.getCurrency(currency).getSymbol();
	}

	@Override
	public Float getPriceByOrderId(Long purchaseOrderId) {

		if (null == purchaseOrderId || purchaseOrderId <= 0) {
			throw new BusinessException(String.format(
					"purchaseOrderId[%s] is illegal", purchaseOrderId));
		}
		return purchaseOrderRepository.findPriceByOrderId(purchaseOrderId);
	}

	@Override
	public void updatePurchaseEstimate(Long purchaseOrderId,
			String evlautionDesc,String evaluationScore4, Date updateTime, String updateBy) {

		this.purchaseOrderRepository.updatePurchaseOrderEstimate(
				purchaseOrderId, evlautionDesc,Double.parseDouble(evaluationScore4), updateTime, updateBy);

	}

	@SuppressWarnings({ "deprecation", "unchecked" })
	@Transactional
	@Override
	public List<TPurchaseOrder> getByPropertyByStatus(String property,
			Object value, Short orderStatus) {
		Session session = (org.hibernate.Session) em.getDelegate();
		Criteria criteria=null;
		
		if(orderStatus==5)
		{
			criteria = session.createCriteria(TPurchaseOrder.class).add(org.hibernate.criterion.Expression.eq(property, value)).
					add(org.hibernate.criterion.Expression.eq("isDelete", false));
		}
		else
		{
			
			Object[] orderStatusArray=new Object[2];
			if(orderStatus==2)//已完成订单
			{
				orderStatusArray[0]=(short)2;
				orderStatusArray[1]=(short)3;
			}
			else//待履行订单
			{
				orderStatusArray[0]=(short)0;
				orderStatusArray[1]=(short)1;
			}
			
			criteria = session.createCriteria(TPurchaseOrder.class).add(org.hibernate.criterion.Expression.eq(property, value)).
					add(org.hibernate.criterion.Expression.eq("isDelete", false)).
					add(org.hibernate.criterion.Expression.in("orderStatus", orderStatusArray));
		}
		return criteria.list();
	}

	@Override
	public void updatePurchaseEstimateManyGrade(Long purchaseOrderId,
			String evlautionDesc, String evaluationScore2,
			String evaluationScore3, String evaluationScore4,
			String evaluationScore5, Date updateTime, String updateBy) {


		this.purchaseOrderRepository.updatePurchaseOrderEstimateManyGrade(
				purchaseOrderId, evlautionDesc,
				Double.parseDouble(evaluationScore2),
				Double.parseDouble(evaluationScore3),
				Double.parseDouble(evaluationScore4),
				Double.parseDouble(evaluationScore5), updateTime, updateBy);
		
	}

}
